#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<map>

using namespace std;


//设计一个只能在堆上创建对象的类
//1.析构函数私有
class HeapOnly1
{
public:
	void Destror()
	{
		delete this;
	}
	HeapOnly1()
	{

	}
private:
	~HeapOnly1()
	{

	}

	HeapOnly1(const HeapOnly1& h) = delete;
	HeapOnly1& operator=(const HeapOnly1& h) = delete;
};

//2.构造函数私有
class HeapOnly2
{
public:
	~HeapOnly2()
	{

	}

	static HeapOnly2* CreateObj()
	{
	    return new HeapOnly2;
	}
private:
	HeapOnly2()
	{

	}

	HeapOnly2(const HeapOnly2 & h) = delete;
	HeapOnly2& operator=(const HeapOnly2 & h) = delete;
};

void test1()
{
	//HeapOnly h1;
	//static HeapOnly h2;
	
	HeapOnly1* h = new  HeapOnly1;
	h->Destror();

	HeapOnly2* h3 = HeapOnly2::CreateObj();

	//HeapOnly h4(h3);
}


//设计一个只能在栈上创建对象的类
//不能将析构函数私有，因为在栈上创建的对象结束后会主动调用析构函数
//构造函数私有
class StackOnly
{
public:
	//不能将拷贝构造私有，不然这边就没办法传值返回了
	static StackOnly CreateObj()
	{
		StackOnly ret;
		return ret;
	}

	~StackOnly()
	{

	}

private:
	StackOnly()
	{

	}

	StackOnly& operator=(const HeapOnly2& h) = delete;
	//将一个类的专属operator new 重载后禁用
	void* operator new(size_t size) = delete;


};

void test2()
{
	//static StackOnly h1;

	//StackOnly* h2 = new  StackOnly;

	StackOnly h3 = StackOnly::CreateObj();
	StackOnly h4(h3);

    //new --> operator new + 构造
	//StackOnly h4 = new StackOnly(h3);
}

//创建一个类不能被继承->构造私有 final关键字

//单例模式-->全局只能创建一个类对象

//饿汉模式-->一开始（main之前）就创建单例对象
//1.如果单例对象初始化的内容很多，会影响启动速度
//2.有两个单例对象，互相有依赖关系
//假设有A类和B累两个单例对象，要求先创建A再创建B，B的初始化创建依赖于A
namespace hungry
{
class singleton
{
public:
	//2.提供一个获取单例对象的接口
	static singleton& GetInstance()
	{
		return _sinst;
	}

	void add(const pair<string, string>& kv)
	{
		_dict[kv.first] = kv.second;
	}
	
	void print()
	{
		for (auto& e: _dict)
		{
			cout << e.first << ":" << e.second << endl;
		}
		cout << endl;
	}
private:
	//1.构造函数私有
	singleton()
	{

	}

	map<string, string> _dict;
	static singleton _sinst;

	//3.防拷贝
	singleton(const singleton& s) = delete;
	singleton& operator=(const singleton& s) = delete;

};
//全局静态--在main函数之前创建
singleton singleton::_sinst;
}

void test3()
{
	cout << &hungry::singleton::GetInstance() << endl;
	cout << &hungry::singleton::GetInstance() << endl;
	cout << &hungry::singleton::GetInstance() << endl;

	hungry::singleton::GetInstance().add({ "xxx","111" });
	hungry::singleton::GetInstance().add({ "yyy","222" });
	hungry::singleton::GetInstance().add({ "zzz","333" });
	hungry::singleton::GetInstance().add({ "zzz","444" });

	hungry::singleton::GetInstance().print();


}


//饿汉模式
namespace lazy
{
	class singleton
	{
	public:
		//2.提供一个获取单例对象的接口
		static singleton& GetInstance()
		{
			//第一次调用的时候才会创建单例对象
			if (_sinst == nullptr)
			{
				_sinst = new singleton;
			}
			return *_sinst;
		}

		//一把情况下单例对象不用显示写释放
		//特殊场景：1.中途需要释放  2.程序结束时，需要做一些特殊动作(持久化)
		static void DelInstance()
		{
			if (_sinst)
			{
				delete _sinst;
				_sinst = nullptr;
			}
		}

		void add(const pair<string, string>& kv)
		{
			_dict[kv.first] = kv.second;
		}

		void print()
		{
			for (auto& e : _dict)
			{
				cout << e.first << ":" << e.second << endl;
			}
			cout << endl;
		}

		class GC
		{
		public:
			~GC()
			{
				lazy::singleton::DelInstance();

			}
		};
	private:
		//1.构造函数私有
		singleton()
		{

		}

		~singleton()
		{
			cout << "~singleton()" << endl;

			//持久化：map写入文件
			FILE* fin = fopen("map.txt", "w");
			for (auto& e : _dict)
			{
				fputs(e.first.c_str(), fin);
				fputs(":", fin);
				fputs(e.second.c_str(), fin);
				fputs("\n", fin);
				
			}
		}

		map<string, string> _dict;
		static singleton* _sinst;
		static GC _gc;

		//3.防拷贝
		singleton(const singleton& s) = delete;
		singleton& operator=(const singleton& s) = delete;


	};
	//全局静态--在main函数之前创建
	singleton* singleton::_sinst = nullptr;
	singleton::GC singleton::_gc;
}

//class GC
//{
//public:
//	~GC()
//	{
//		lazy::singleton::DelInstance();
//
//	}
//};
//
//GC gc;

void test4()
{
	cout << &lazy::singleton::GetInstance() << endl;
	cout << &lazy::singleton::GetInstance() << endl;
	cout << &lazy::singleton::GetInstance() << endl;

	lazy::singleton::GetInstance().add({ "xxx","111" });
	lazy::singleton::GetInstance().add({ "yyy","222" });
	lazy::singleton::GetInstance().add({ "zzz","333" });
	lazy::singleton::GetInstance().add({ "zzz","444" });

	lazy::singleton::GetInstance().print();


	//lazy::singleton::DelInstance();
	//lazy::singleton::GetInstance().add({ "zzz","444" });
	//lazy::singleton::GetInstance().print();

}


int main()
{
	test3();
	cout << "-------------------------------------------------------------------" << endl;

	test4();

	return 0;
}